#!/bin/bash
#
# This script will find eosd processes which have hung
# while umounting (caused by upstream xroot issue:
# https://github.com/xrootd/xrootd/issues/418).
#
# Author: Dan van der Ster
# Date: 26 Sept 2016
# 
# Modified by Haibo Li, 28 July 2023
#

export PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin

# make sure we have lsof
#which lsof &>/dev/null || exit

# Wrap cleanup procedures under a lock, not to run the script more than once
(
        flock -n 9;
        if [ $? -ne 0 ]; then
                echo "Still running this script... terminating"
                exit 1
        fi

	# 1) Find running eosxd processes
	PIDS=$(pidof eosxd)

	function waitorkill {
		PID=$1
		for _ in {0..12}; do
			if ! grep -qs eosxd "/proc/${PID}/cmdline"; then
				logger -t eos-cleanup.sh "eosxd process ${PID} finished before killing it"
				return
			fi
			sleep 5
		done
		logger -t eos-cleanup.sh "eosxd process ${PID} will be killed with SIGQUIT"
		grep -qs eosxd "/proc/${PID}/cmdline" && kill -QUIT "${PID}" 2>/dev/null
	}
	# Kill the processes that don't have /dev/fuse open
	for PID in $PIDS
	do
		if ! lsof -b -n -p "${PID}" 2>/dev/null | grep -q /dev/fuse
		then
			# kill PID if it is still eos[x]d. This is racey.
			CMDLINE=$(cat "/proc/${PID}/cmdline")
			logger -t eos-cleanup.sh "eosxd process ${PID} which doesn't have /dev/fuse open. CMDLINE=${CMDLINE}"
			waitorkill "${PID}" & # spawn a conditional kill after +60 seconds
		fi
	done
	wait # wait on all the processes that may be exiting (either by sigkill or a normal exit that happened in the meantime)

	# 2) Find mounts in /eos/* which do not have a corresponding eosxd
	# ONLY IF AUTOFS!!
	if [ -f /etc/auto.eos ]
	then
		# eosxd mounts have type fuse and are mounted in /eos/*
		EOSXD_MOUNTS=$(grep -E '\bfuse\b' /proc/mounts | grep -v '^eos' | awk '{print $2}' | grep '^/eos/')
		for MOUNT in $EOSXD_MOUNTS
		do
			EOSXD=$(pgrep -u root -f "eosxd ${MOUNT}")
			if [[ -z "${EOSXD}" ]]
			then
				logger -t eos-cleanup.sh "${MOUNT} is mounted but corresponding eosxd is not running. Unmounting."
				umount -l "${MOUNT}"
			fi
		done
	fi

	# 3) Find mounts in /eos/* which do not have a corresponding eosxd
	# Roberto V: ONLY USING NEW CONFIG LAYOUT
	if [[ -f /etc/auto.master.d/eos.autofs ]]
	then
			# eosxd mounts have type fuse and are mounted in /eos/*
			EOSXD_MOUNTS=$(grep -E '\bfuse\b' /proc/mounts | grep -v '^eos' | awk '{print $2}' | grep '^/eos/')
			for MOUNT in $EOSXD_MOUNTS
			do
				EOSXD=$(pgrep -u root -f "eosxd ${MOUNT}")
				if [[ -z "${EOSXD}" ]]
				then
						logger -t eos-cleanup.sh "${MOUNT} is mounted but corresponding eosxd is not running. Unmounting."
						umount -l "${MOUNT}"
				fi

				stat "${MOUNT}" >  /dev/null 2>&1
				if [ $? -ne 0 ]; then
        			#	/bin/echo "SERVICE STATUS: failed to access ${MOUNT}"
        				umount -l ${MOUNT}
				fi

			done
	fi

) 9>/tmp/eos-cleanup.lock

echo "EOS mount clean is OK"
exit 0

